use actix_web::{post, web::ServiceConfig, Scope};
use serde::{Deserialize, Serialize};

use crate::{error::AppErr, store::dev_file::{self, DevFile}, web::{req::Cbor, res::{new_body, CborResp, DownloadResp, VoidResp}, session::Session}};

#[derive(Debug, Deserialize)]
struct CreateReq {
    name: String,
    type_id: i64,
    version: String,
    description: String,

    #[serde(with = "serde_bytes")]
    body: Box<[u8]>,
}

#[derive(Debug, Serialize)]
struct IdReq {
    id: i64,
}

#[post("/create")]
async fn create(_s: Session, req: Cbor<CreateReq>) -> CborResp<IdReq> {
    let id = dev_file::create(&req.name, req.type_id, &req.version, &req.description, &req.body).await?;
    new_body( IdReq { id } )
}

#[derive(Debug, Deserialize)]
struct QueryReq {
    type_id: i64,
}

#[post("/query")]
async fn query(_s: Session, req: Cbor<QueryReq>) -> CborResp<Box<[DevFile]>> {
    new_body( dev_file::query(req.type_id).await? )
}

#[derive(Debug, Deserialize)]
struct DeleteReq {
    id: i64,
}

#[post("/delete")]
async fn delete(_s: Session, req: Cbor<DeleteReq>) -> Result<VoidResp, AppErr> {
    dev_file::delete(req.id).await?;
    Ok(VoidResp)
}

type GetReq = DeleteReq;

#[post("/get")]
async fn get(_s: Session, req: Cbor<GetReq>) -> Result<DownloadResp, AppErr> {
    let (name, body) = dev_file::get(req.id).await?;
    Ok( DownloadResp::new(name, body) )
}

pub fn register(cfg: &mut ServiceConfig) {
    let scope = Scope::new("/dev_file")
        .service(create)
        .service(query)
        .service(delete)
        .service(get)
        ;
    cfg.service(scope);
}
